package com.hancher.gamelife2.noisedetect;

import android.media.MediaRecorder;

import com.hancher.common.androidutil.AsyncUtils;
import com.hancher.common.androidutil.LogUtil;

import java.io.File;
import java.io.IOException;
import java.util.Arrays;

import io.reactivex.rxjava3.disposables.Disposable;
import io.reactivex.rxjava3.functions.Consumer;

/**
 * 作者 : Hancher ytu_shaoweijie@163.com <br/>
 * 时间 : 2023/4/22 12:51 <br/>
 * 描述 :
 */
public class FrequencyUtil {
    private final String TAG = "MediaRecord";
    private MediaRecorder mMediaRecorder;
    public static final int MAX_LENGTH = 1000 * 60 * 10;// 最大录音时长1000*60*10;
    private String filePath;
    private Disposable d;

    public FrequencyUtil() {
        this.filePath = "/dev/null";
    }

    public FrequencyUtil(File file) {
        this.filePath = file.getAbsolutePath();
    }

    private long startTime;
    private long endTime;

    /**
     * 开始录音 使用amr格式
     *
     *            录音文件
     * @return
     */
    public void startRecord() {
        // 开始录音
        /* ①Initial：实例化MediaRecorder对象 */
        if (mMediaRecorder == null)
            mMediaRecorder = new MediaRecorder();
        try {
            /* ②setAudioSource/setVedioSource */
            mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);// 设置麦克风
            /* ②设置音频文件的编码：AAC/AMR_NB/AMR_MB/Default 声音的（波形）的采样 */
            mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
            /*
             * ②设置输出文件的格式：THREE_GPP/MPEG-4/RAW_AMR/Default THREE_GPP(3gp格式
             * ，H263视频/ARM音频编码)、MPEG-4、RAW_AMR(只支持音频且音频编码要求为AMR_NB)
             */
            mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
            /*
             * 设置录音的音频采样率。在prepare()之前调用这个方法。Prepare()可能会对参数执行额外的检查，以确保指定的音频采样率是否适用。
             * 采样率实际上取决于音频录制的格式，以及平台的功能。
             * 例如，AAC音频编码标准支持的采样率范围为8 ~ 96khz, AMRNB支持的采样率为8kHz, AMRWB支持的采样率为16kHz。
             * 支持的音频采样率请参考相关音频编码标准。
             * 参数:
             * samplingRate -音频的采样率(每秒采样数)。
             */
            mMediaRecorder.setAudioSamplingRate(8000);
            /* ③准备 */
            mMediaRecorder.setOutputFile(filePath);
            mMediaRecorder.setMaxDuration(MAX_LENGTH);
            mMediaRecorder.prepare();
            /* ④开始 */
            mMediaRecorder.start();
            // AudioRecord audioRecord.
            /* 获取开始时间* */
            startTime = System.currentTimeMillis();
            if (d != null) {
                if (!d.isDisposed()) {
                    d.dispose();
                }
            }
            d = AsyncUtils.run(emitter -> {
                // 这个工具类目前只能处理8的倍数
                int pointCount = 512;
                int[] amplitudes = new int[pointCount];
                Complex[] amplitudesIn = new Complex[pointCount];
                Double[] models;
                while (true) {
                    for (int i = 0; i < pointCount; i++) {
                        try {
                            amplitudes[i] = mMediaRecorder.getMaxAmplitude();
                        } catch (Exception ignored) {

                        }
                        try {
                            Thread.sleep(1);
                        } catch (Exception ignored) {
                        }
                    }
                    for (int i = 0; i < pointCount; i++) {
                        amplitudesIn[i] = new Complex(amplitudes[i], 0);
                    }
                    amplitudesIn = FFT.getFFT(amplitudesIn, pointCount);
                    models = Complex.toModArray(amplitudesIn);
                    for (int i = 0; i < pointCount; i++) {
                        models[i] = models[i] / pointCount * 2;
                    }
                    emitter.onNext(models);
                }

            }, (Consumer<Double[]>) s -> {
                LogUtil.o("傅里叶结果：" + Arrays.toString(s));
                listener.onDbChange(s);
            });
            LogUtil.i("ACTION_START", "startTime" + startTime);
        } catch (IllegalStateException | IOException e) {
            LogUtil.i(TAG, "call startAmr(File mRecAudioFile) failed!" + e.getMessage());
        }
    }

    /**
     * 停止录音
     *
     */
    public long stopRecord() {
        if (d != null) {
            if (!d.isDisposed()) {
                d.dispose();
            }
        }
        if (mMediaRecorder == null)
            return 0L;
        endTime = System.currentTimeMillis();
        LogUtil.i("ACTION_END", "endTime" + endTime);
        mMediaRecorder.stop();
        mMediaRecorder.reset();
        mMediaRecorder.release();
        mMediaRecorder = null;
        LogUtil.i("ACTION_LENGTH", "Time" + (endTime - startTime));
        return endTime - startTime;
    }

    private DbListener listener;

    public FrequencyUtil setListener(DbListener listener) {
        this.listener = listener;
        return this;
    }

    interface DbListener {
        /**
         * 录音实时解析参数
         *
         * @param frequency
         */
        void onDbChange(Double[] frequency);
    }
}
